﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Volo.Abp.DependencyInjection;

namespace Abp.DbMigrator
{
    public class BookDbMiagratorService : ITransientDependency
    {
        public ILogger<BookDbMiagratorService> Logger { get; set; }

        public BookDbMiagratorService()
        {
            Logger = NullLogger<BookDbMiagratorService>.Instance;
        }

        public async Task MigratorAsync()
        {
            var initialMaigrationAdded = AddInitialMigrationIfNotExist();
            if (initialMaigrationAdded)
            {
                return;
            }
            UpdateInitialMigration();
        }

        private bool AddInitialMigrationIfNotExist()
        {
            try
            {
                // 如果迁移文件夹不存在，则创建迁移文件夹
                if (!MigrationsFolderExists())
                {
                    // 初始化迁移
                    AddInitialMigration();
                    return true;
                }

                return false;
            }
            catch (Exception e)
            {
                Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
                return false;
            }
        }

        // 判断迁移文件夹是否存在
        private bool MigrationsFolderExists()
        {
            // 获取迁移文件夹路径
            var dbMigrationsProjectFolder = GetDbMigratorProjectFolderPath();

            return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
        }

        // 更新初始化迁移脚本到数据库
        private void UpdateInitialMigration()
        {
            Logger.LogInformation("Update initial migration...");

            string argumentPrefix;
            string fileName;

            // 如果是mac或linux，则使用-c参数，否则使用/C参数
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                argumentPrefix = "-c";
                fileName = "/bin/bash";
            }
            else
            {
                argumentPrefix = "/C";
                fileName = "cmd.exe";
            }

            // 创建迁移脚本
            var procStartInfo = new ProcessStartInfo(fileName, $"{argumentPrefix} dotnet ef database update");
            procStartInfo.WorkingDirectory = GetDbMigratorProjectFolderPath();

            try
            {
                // 创建迁移
                Process.Start(procStartInfo);
            }
            catch (Exception ex)
            {
                Logger.LogError("Update initial migration...", ex.Message);
                throw new Exception("Couldn't run dotnet ef migrations...");
            }
        }

        // 初始化迁移
        private void AddInitialMigration()
        {
            Logger.LogInformation("Creating initial migration...");

            string argumentPrefix;
            string fileName;

            // 如果是mac或linux，则使用-c参数，否则使用/C参数
            if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                argumentPrefix = "-c";
                fileName = "/bin/bash";
            }
            else
            {
                argumentPrefix = "/C";
                fileName = "cmd.exe";
            }

            // 创建迁移脚本
            var procStartInfo = new ProcessStartInfo(fileName, $"{argumentPrefix} dotnet ef migrations add InitialCreate");
            procStartInfo.WorkingDirectory = GetDbMigratorProjectFolderPath();

            try
            {
                // 创建迁移
                Process.Start(procStartInfo);
            }
            catch (Exception ex)
            {
                Logger.LogError("Creating initial migration...", ex.Message);
                throw new Exception("Couldn't run dotnet ef migrations...");
            }
        }

        // 获取迁移文件夹路径
        private string GetDbMigratorProjectFolderPath()
        {
            var slnDirectoryPath = GetSolutionDirectoryPath(); // 获取solution文件夹路径

            if (slnDirectoryPath == null)
            {
                throw new Exception("Solution folder not found!");
            }

            var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src");

            return Directory.GetDirectories(srcDirectoryPath).FirstOrDefault(d => d.EndsWith(".DbMigrator")); // 获取迁移文件夹路径
        }

        // 获取solution文件夹路径
        private string GetSolutionDirectoryPath()
        {
            var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());

            while (Directory.GetParent(currentDirectory.FullName) != null)
            {
                currentDirectory = Directory.GetParent(currentDirectory.FullName);

                if (Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
                {
                    return currentDirectory.FullName;
                }
            }
            return null;
        }
    }
}
